/**
 * 防抖函数
 * 在事件被触发 n 秒后再执行回调，如果在这 n 秒内又被触发，则重新计时
 * 
 * @param {Function} func - 需要防抖的函数
 * @param {number} wait - 延迟执行的时间（毫秒）
 * @param {boolean} immediate - 是否立即执行（true: 立即执行，false: 延迟执行）
 * @returns {Function} 防抖处理后的函数
 */
function debounce (func, wait, immediate) {
    // 存储定时器ID
    let timeout;

    return function (...args) {
        // 保存当前函数的执行上下文（this）
        const context = this;

        // 如果设置了立即执行，且当前没有待执行的定时器，则标记为立即执行
        const callNow = immediate && !timeout;
        console.log(immediate);
        // 清除之前的定时器，重新计时
        clearTimeout(timeout);

        // 设置新的定时器
        timeout = setTimeout(() => {
            // 定时器执行后，清空timeout标识
            timeout = null;
            // 如果不是立即执行模式，则在延迟后执行函数
            if (!immediate) {
                func.apply(context, args);
            }
        }, wait)

        // 如果是立即执行模式，且当前没有待执行的定时器，则立即执行
        if (callNow) {
            func.apply(context, args);
            immediate = false;
        };
    }
}

function debounce2 (fn, wait) {
    let timer = null;
    return function (...args) {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, wait);
    }
}

/**
 * 节流函数
 * 在一个单位时间内，只允许一个函数被执行
 * 
 * @param {Function} func - 需要节流的函数
 * @param {number} wait - 延迟执行的时间（毫秒）
 * @param {object} options - 配置对象
 * @param {boolean} options.leading - 是否首次执行
 * @param {boolean} options.trailing - 是否最后一次执行
 * @returns {Function} 节流处理后的函数
 */
function throttle (func, wait, options = {}) {
    // 存储上一次函数执行的时间戳
    let previous = 0;
    // 首次执行标记
    let isFirst = true;

    return function (...args) {
        // 获取当前时间戳
        const now = Date.now();
        // 首次执行且首次执行标记为true，则执行函数并标记为false
        if (isFirst && options.leading) {
            func.apply(this, args);
            isFirst = false;
        }
        // 计算剩余时间
        const remaining = wait - (now - previous);
        // 如果剩余时间小于等于0，则执行函数并更新时间戳
        if (remaining <= 0) {
            func.apply(this, args);
            previous = now;
            // 重置首次执行标记
            isFirst = true;
        }
        // 如果剩余时间大于0，则设置定时器
        else if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                previous = Date.now();
                func.apply(this, args);
            }, remaining);
        }
    }
}
function throttle2 (fn, wait) {
    let canRun = true; //通过闭包保存一个标记
    return function (...args) {
        if (!canRun) return; //在函数开头判断标记是否为true,不为true则return
        canRun = false;
        setTimeout(() => {
            fn.apply(this, args);
            canRun = true;
        }, wait)
    }
}

function fn1 (fn, wait) {
    let timer = null;

    return function (...args) {
        timer && clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, wait)
    }
}

function fm1 (fn, wait) {
    let canRun = true;
    return function (...args) {
        if (!canRun) return;
        canRun = false;
        setTimeout(() => {
            fn.apply(this, args);
            canRun = true;
        }, wait)
    }
}